import Question, { QuestionDocument } from '../models/questionModel';
import { QuestionType, QuestionDifficulty } from '../middleware/validators/questionValidator';
import { createError } from '../types/errors';
import { log } from '../utils/logger';

export class QuestionService {
  /**
   * 根据类型获取问题
   */
  static async getQuestionsByType(type: QuestionType): Promise<QuestionDocument[]> {
    try {
      return await Question.find({ type });
    } catch (error) {
      log.error('获取问题失败', {
        context: 'QuestionService.getQuestionsByType',
        type,
        error
      });
      throw error;
    }
  }

  /**
   * 根据标签获取问题
   */
  static async getQuestionsByTags(tags: string[]): Promise<QuestionDocument[]> {
    try {
      return await Question.find({ tags: { $in: tags } });
    } catch (error) {
      log.error('获取问题失败', {
        context: 'QuestionService.getQuestionsByTags',
        tags,
        error
      });
      throw error;
    }
  }

  /**
   * 获取推荐问题
   */
  static async getRecommendedQuestions(
    userId: string,
    count: number = 5
  ): Promise<QuestionDocument[]> {
    try {
      // TODO: 实现更复杂的推荐逻辑
      return await Question.find()
        .sort({ createdAt: -1 })
        .limit(count);
    } catch (error) {
      log.error('获取推荐问题失败', {
        context: 'QuestionService.getRecommendedQuestions',
        userId,
        error
      });
      throw error;
    }
  }

  /**
   * 分析问题难度
   */
  static async analyzeQuestionDifficulty(questionId: string): Promise<{
    difficulty: QuestionDifficulty;
    metrics: Record<string, number>;
  }> {
    try {
      const question = await Question.findById(questionId);
      if (!question) {
        throw createError('NOT_FOUND', '问题不存在');
      }

      // 计算难度指标
      const metrics = {
        complexityScore: this.calculateComplexityScore(question),
        timeScore: this.calculateTimeScore(question.timeLimit || 0),
        pointsScore: this.calculatePointsScore(question.points || 0)
      };

      // 根据指标确定难度
      const averageScore = (metrics.complexityScore + metrics.timeScore + metrics.pointsScore) / 3;
      let difficulty: QuestionDifficulty;

      if (averageScore <= 0.25) {
        difficulty = QuestionDifficulty.EASY;
      } else if (averageScore <= 0.5) {
        difficulty = QuestionDifficulty.MEDIUM;
      } else if (averageScore <= 0.75) {
        difficulty = QuestionDifficulty.HARD;
      } else {
        difficulty = QuestionDifficulty.EXPERT;
      }

      return { difficulty, metrics };
    } catch (error) {
      log.error('分析问题难度失败', {
        context: 'QuestionService.analyzeQuestionDifficulty',
        questionId,
        error
      });
      throw error;
    }
  }

  /**
   * 获取问题统计信息
   */
  static async getQuestionStats() {
    try {
      const [totalCount, typeStats, difficultyStats] = await Promise.all([
        Question.countDocuments(),
        Question.aggregate([
          {
            $group: {
              _id: '$type',
              count: { $sum: 1 }
            }
          }
        ]),
        Question.aggregate([
          {
            $group: {
              _id: '$difficulty',
              count: { $sum: 1 }
            }
          }
        ])
      ]);

      return {
        totalCount,
        typeDistribution: typeStats.reduce((acc, { _id, count }) => {
          acc[_id] = count;
          return acc;
        }, {} as Record<string, number>),
        difficultyDistribution: difficultyStats.reduce((acc, { _id, count }) => {
          acc[_id] = count;
          return acc;
        }, {} as Record<string, number>)
      };
    } catch (error) {
      log.error('获取问题统计信息失败', {
        context: 'QuestionService.getQuestionStats',
        error
      });
      throw error;
    }
  }

  /**
   * 验证问题答案
   */
  static async validateAnswer(questionId: string, submittedAnswer: any): Promise<{
    isCorrect: boolean;
    feedback?: string;
    score?: number;
  }> {
    try {
      const question = await Question.findById(questionId);
      if (!question) {
        throw createError('NOT_FOUND', '问题不存在');
      }

      let isCorrect = false;
      let score = 0;
      let feedback = '';

      switch (question.type) {
        case QuestionType.SINGLE_CHOICE:
        case QuestionType.MULTIPLE_CHOICE:
          isCorrect = this.validateChoiceAnswer(question, submittedAnswer);
          score = isCorrect ? (question.points || 0) : 0;
          break;
        case QuestionType.TRUE_FALSE:
          isCorrect = submittedAnswer === question.correctAnswer;
          score = isCorrect ? (question.points || 0) : 0;
          break;
        case QuestionType.SHORT_ANSWER:
          const shortAnswerResult = this.validateShortAnswer(question, submittedAnswer);
          isCorrect = shortAnswerResult.isCorrect;
          score = shortAnswerResult.score;
          feedback = shortAnswerResult.feedback;
          break;
        case QuestionType.ESSAY:
          const essayResult = await this.evaluateEssay(question, submittedAnswer);
          isCorrect = true; // 论述题不判断对错
          score = essayResult.score;
          feedback = essayResult.feedback;
          break;
      }

      return { isCorrect, score, feedback };
    } catch (error) {
      log.error('验证答案失败', {
        context: 'QuestionService.validateAnswer',
        questionId,
        error
      });
      throw error;
    }
  }

  // 私有辅助方法

  /**
   * 计算复杂度分数
   */
  private static calculateComplexityScore(question: QuestionDocument): number {
    let score = 0;

    // 根据问题类型计算基础分数
    switch (question.type) {
      case QuestionType.TRUE_FALSE:
        score += 0.2;
        break;
      case QuestionType.SINGLE_CHOICE:
        score += 0.4;
        break;
      case QuestionType.MULTIPLE_CHOICE:
        score += 0.6;
        break;
      case QuestionType.SHORT_ANSWER:
        score += 0.8;
        break;
      case QuestionType.ESSAY:
        score += 1.0;
        break;
    }

    // 考虑其他因素
    if (question.keywords?.length) {
      score += 0.1 * Math.min(question.keywords.length, 5);
    }
    if (question.rubric?.length) {
      score += 0.1 * Math.min(question.rubric.length, 5);
    }

    return Math.min(score, 1);
  }

  /**
   * 计算时间分数
   */
  private static calculateTimeScore(timeLimit: number): number {
    const minutes = timeLimit / 60;
    if (minutes <= 1) return 0.2;
    if (minutes <= 3) return 0.4;
    if (minutes <= 5) return 0.6;
    if (minutes <= 10) return 0.8;
    return 1.0;
  }

  /**
   * 计算分值分数
   */
  private static calculatePointsScore(points: number): number {
    if (points <= 5) return 0.2;
    if (points <= 10) return 0.4;
    if (points <= 20) return 0.6;
    if (points <= 50) return 0.8;
    return 1.0;
  }

  /**
   * 验证选择题答案
   */
  private static validateChoiceAnswer(question: QuestionDocument, answer: any): boolean {
    if (!question.options) return false;

    const correctOptions = question.options
      .filter(option => option.isCorrect)
      .map(option => option.content);

    if (question.type === QuestionType.SINGLE_CHOICE) {
      return correctOptions.includes(answer);
    } else {
      // 多选题
      if (!Array.isArray(answer)) return false;
      return (
        answer.length === correctOptions.length &&
        answer.every(a => correctOptions.includes(a))
      );
    }
  }

  /**
   * 验证简答题答案
   */
  private static validateShortAnswer(
    question: QuestionDocument,
    submittedAnswer: string
  ): { isCorrect: boolean; score: number; feedback: string } {
    if (!question.answer?.content) {
      return { isCorrect: false, score: 0, feedback: '答案未定义' };
    }

    const keywords = question.keywords || [];
    const matchedKeywords = keywords.filter(keyword =>
      submittedAnswer.toLowerCase().includes(keyword.toLowerCase())
    );

    const keywordScore = keywords.length > 0
      ? (matchedKeywords.length / keywords.length) * (question.points || 0)
      : 0;

    const isCorrect = matchedKeywords.length > 0;
    const score = Math.round(keywordScore);
    const feedback = `匹配到 ${matchedKeywords.length}/${keywords.length} 个关键词`;

    return { isCorrect, score, feedback };
  }

  /**
   * 评估论述题答案
   */
  private static async evaluateEssay(
    question: QuestionDocument,
    submittedAnswer: string
  ): Promise<{ score: number; feedback: string }> {
    if (!question.rubric) {
      return { score: 0, feedback: '评分标准未定义' };
    }

    // TODO: 实现更复杂的评分逻辑，可能需要使用AI服务
    const totalPoints = question.rubric.reduce((sum, item) => sum + item.points, 0);
    
    // 简单示例：根据答案长度和评分标准计算分数
    const answerLength = submittedAnswer.length;
    const lengthScore = Math.min(answerLength / 500, 1); // 假设500字为满分
    const score = Math.round(totalPoints * 0.6 * lengthScore);
    
    const feedback = `使用评分标准进行了基本评估，答案长度：${answerLength}字`;

    return { score, feedback };
  }
}
